﻿#include "IniReader.h"

InIReader::InIReader(const std::string &fileName) : _contents(std::vector<std::string>()), _fileName(fileName)
{

    try
    {
        if (FileSystem::fileExists(_fileName))
        {
            _contents.AddRange(File::ReadAllLines(_fileName));
        }
    }
    catch (...)
    {
    }
}

std::string InIReader::FindValue(const std::string &section, const std::string &key)
{
    for (int a = 0; a < _contents.size(); a++)
    {
        if (_contents[a].compare("[" + section + "]") == 0)
        {
            for (int b = a + 1; b < _contents.size(); b++)
            {
                if (StringHelper::split(_contents[b], '=')[0].compare(key) == 0)
                {
                    return StringHelper::split(_contents[b], '=')[1];
                }
                else if (StringHelper::startsWith(_contents[b], "[") && StringHelper::endsWith(_contents[b], "]"))
                {
                    return "";
                }
            }
        }
    }
    return "";
}

int InIReader::FindIndex(const std::string &section, const std::string &key)
{
    for (int a = 0; a < _contents.size(); a++)
    {
        if (_contents[a].compare("[" + section + "]") == 0)
        {
            for (int b = a + 1; b < _contents.size(); b++)
            {
                if (StringHelper::split(_contents[b], '=')[0].compare(key) == 0)
                {
                    return b;
                }
                else if (StringHelper::startsWith(_contents[b], "[") && StringHelper::endsWith(_contents[b], "]"))
                {
                    _contents.Insert(b - 1, key + "=");
                    return b - 1;
                }
                else if (_contents.size() - 1 == b)
                {
                    _contents.push_back(key + "=");
                    return _contents.size() - 1;
                }
            }
        }
    }
    if (_contents.size() > 0)
    {
        _contents.push_back("");
    }

    _contents.push_back("[" + section + "]");
    _contents.push_back(key + "=");
    return _contents.size() - 1;
}

void InIReader::Save()
{
    try
    {
        File::WriteAllLines(_fileName, _contents);
    }
    catch (...)
    {
    }
}

bool InIReader::ReadBoolean(const std::string &section, const std::string &key, bool Default, bool writeWhenNull)
{
    bool result;

    if (!bool::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

unsigned char InIReader::ReadByte(const std::string &section, const std::string &key, unsigned char Default, bool writeWhenNull)
{
    unsigned char result;

    if (!unsigned char::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }


    return result;
}

signed char InIReader::ReadSByte(const std::string &section, const std::string &key, signed char Default, bool writeWhenNull)
{
    signed char result;

    if (!signed char::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }


    return result;
}

unsigned short InIReader::ReadUInt16(const std::string &section, const std::string &key, unsigned short Default, bool writeWhenNull)
{
    unsigned short result;

    if (!unsigned short::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }


    return result;
}

short InIReader::ReadInt16(const std::string &section, const std::string &key, short Default, bool writeWhenNull)
{
    short result;

    if (!short::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }


    return result;
}

unsigned int InIReader::ReadUInt32(const std::string &section, const std::string &key, unsigned int Default, bool writeWhenNull)
{
    unsigned int result;

    if (!unsigned int::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

int InIReader::ReadInt32(const std::string &section, const std::string &key, int Default, bool writeWhenNull)
{
    int result;

    if (!int::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

unsigned long long InIReader::ReadUInt64(const std::string &section, const std::string &key, unsigned long long Default, bool writeWhenNull)
{
    unsigned long long result;

    if (!unsigned long long::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

long long InIReader::ReadInt64(const std::string &section, const std::string &key, long long Default, bool writeWhenNull)
{
    long long result;

    if (!long long::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }


    return result;
}

float InIReader::ReadSingle(const std::string &section, const std::string &key, float Default, bool writeWhenNull)
{
    float result;

    if (!float::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

double InIReader::ReadDouble(const std::string &section, const std::string &key, double Default, bool writeWhenNull)
{
    double result;

    if (!double::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

Decimal InIReader::ReadDecimal(const std::string &section, const std::string &key, Decimal Default, bool writeWhenNull)
{
    Decimal result;

    if (!Decimal::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

std::string InIReader::ReadString(const std::string &section, const std::string &key, const std::string &Default, bool writeWhenNull)
{
    std::string result = FindValue(section, key);

    if (result.empty())
    {
        result = Default;

        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

char InIReader::ReadChar(const std::string &section, const std::string &key, char Default, bool writeWhenNull)
{
    char result;

    if (!char::TryParse(FindValue(section, key), result))
    {
        result = Default;
        if (writeWhenNull)
        {
            Write(section, key, Default);
        }
    }

    return result;
}

Point *InIReader::ReadPoint(const std::string &section, const std::string &key, Point *Default)
{
    std::string temp = FindValue(section, key);
    int tempX, tempY;
    if (temp == "" || !int::TryParse(StringHelper::split(temp, ',')[0], tempX))
    {
        Write(section, key, Default);
        return Default;
    }
    if (!int::TryParse(StringHelper::split(temp, ',')[1], tempY))
    {
        Write(section, key, Default);
        return Default;
    }

    return new Point(tempX, tempY);
}

Size *InIReader::ReadSize(const std::string &section, const std::string &key, Size *Default)
{
    std::string temp = FindValue(section, key);
    int tempX, tempY;
    if (!int::TryParse(StringHelper::split(temp, ',')[0], tempX))
    {
        Write(section, key, Default);
        return Default;
    }
    if (!int::TryParse(StringHelper::split(temp, ',')[1], tempY))
    {
        Write(section, key, Default);
        return Default;
    }

    return new Size(tempX, tempY);
}

TimeSpan InIReader::ReadTimeSpan(const std::string &section, const std::string &key, TimeSpan Default)
{
    TimeSpan result;

    if (!TimeSpan::TryParse(FindValue(section, key), result))
    {
        result = Default;
        Write(section, key, Default);
    }


    return result;
}

float InIReader::ReadFloat(const std::string &section, const std::string &key, float Default)
{
    float result;

    if (!float::TryParse(FindValue(section, key), result))
    {
        result = Default;
        Write(section, key, Default);
    }

    return result;
}

void InIReader::Write(const std::string &section, const std::string &key, bool value)
{
    _contents[FindIndex(section, key)] = key + "=" + StringHelper::toString(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, unsigned char value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, signed char value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, unsigned short value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, short value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, unsigned int value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, int value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, unsigned long long value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, long long value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, float value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, double value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, Decimal value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, const std::string &value)
{
    _contents[FindIndex(section, key)] = key + "=" + value;
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, char value)
{
    _contents[FindIndex(section, key)] = key + "=" + StringHelper::toString(value);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, Point *value)
{
    _contents[FindIndex(section, key)] = key + "=" + value->X + "," + value->Y;
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, Size *value)
{
    _contents[FindIndex(section, key)] = key + "=" + std::to_string(value->Width) + "," + std::to_string(value->Height);
    Save();
}

void InIReader::Write(const std::string &section, const std::string &key, TimeSpan value)
{
    _contents[FindIndex(section, key)] = key + "=" + value;
    Save();
}
